package com.springmvc.context;

import com.springmvc.annotation.Autowired;
import com.springmvc.annotation.Controller;
import com.springmvc.annotation.Service;
import com.springmvc.utils.XmlParser;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebApplicationContext {
    private String contextConfigLocation;
    private List<String> list = new ArrayList();
    private Map<String, Object> iocMap = new ConcurrentHashMap<String, Object>();


    public WebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;

    }

    //初始化spring容器
    public void refresh() {
        //加载xml文件 用dom4j
        String basePackage = XmlParser.getBasePackage(this.contextConfigLocation.split(":")[1]);
        System.out.println(basePackage);
        String[] packages = basePackage.split(",");
        if (packages.length > 0) {
            //遍历执行
            for (String p : packages) {
                //获取包中类的全限定名称
                executeScanPackage(p);
            }
        }
        //present //利用反射创建注解标识过的对象
        executeInstance();
        System.out.println("iocMap:" + iocMap);
        //spring 对象的依赖注入 @autowired
        executeAutowired();

    }

    //获取包中类的全限定名称
    public void executeScanPackage(String pack) {
        System.out.println("/"+pack.replaceAll("\\.", "/"));
        URL url = this.getClass().getClassLoader().getResource(pack.replaceAll("\\.", "/"));
        System.out.println(url);// /E:/IDEA/IDEA_java/boot-start/PrivateSpringMvc/target/classes/com/controller
        String path = url.getFile();
        System.out.println("url:" + url);
        System.out.println("path:" + path);// /E:/IDEA/IDEA_java/boot-start/PrivateSpringMvc/target/classes/com/controller
        File file = new File(path);
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                executeScanPackage(pack + "." + f.getName());
            } else {
                //将全限定类名添加到集合
                String name = pack + "." + f.getName().replaceAll(".class", "");
                list.add(name);
            }
        }

        for (String s : list) {
            System.out.println(s);
        }
    }

    //实例化spring容器对象
    public void executeInstance() {
        if (list.size() == 0) {
            throw new RuntimeException("error");
        }

        //利用反射创建注解标识过的对象
        try {
            for (String className : list) {
                //com.controller.UserController
                Class<?> aClass = Class.forName(className);

                String simpleName = aClass.getSimpleName();
                //userController
                String beanName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);

                if (aClass.isAnnotationPresent(Controller.class)) {

                    //反射创建对象放入map集合
                    iocMap.put(beanName, aClass.newInstance());
                } else if (aClass.isAnnotationPresent(Service.class)) {
                    Service annotation = aClass.getAnnotation(Service.class);
                    if ("".equals(annotation.value())) {
                        iocMap.put(beanName, aClass.newInstance());
                    } else {
                        iocMap.put(annotation.value(), aClass.newInstance());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

    //spring 对象的依赖注入 autowired
    public void executeAutowired() {
        /**
         * 遍历iocMp集合 看里面的对象字段是否被@Autowired 标识
         */
        if (iocMap.isEmpty()) {
            throw new RuntimeException("容器中没有实例对象");
        }

        for (Map.Entry<String, Object> map : iocMap.entrySet()) {
            Object value = map.getValue();
            Field[] fields = value.getClass().getDeclaredFields();
            for (Field field : fields) {

                if (field.isAnnotationPresent(Autowired.class)) {
                    String beanName = field.getAnnotation(Autowired.class).value();
                    //当注解value没有值时
                    if ("".equals(beanName)) {
                        //注入对象
                        field.setAccessible(true);
                        //得到类型全限定名
                        String type = field.getType().getSimpleName();
                        beanName = type.substring(0, 1).toLowerCase() + type.substring(1);
                    }

                    try {

                        field.set(value, iocMap.get(beanName));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }

                }
            }

        }
    }
}
